package edu.mbb.core;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.mbb.annocation.Controller;
import edu.mbb.annocation.RequestMapping;
import edu.mbb.ioc.BeanFactory;

public class DispatcherServlet extends HttpServlet {
	// mvc的核心控制类
	// 解析对应的 requestMapping
	private Map<String, Method> handlerMapping = new HashMap<>();
	// 处理controller 的 类 特殊处理
	private Map<String, Object> controllerMap = new HashMap<>();

	@Override
	public void init(ServletConfig config) throws ServletException {
		// 初始化handler映射
		initHandlerMapping();
	}

	private void initHandlerMapping() {
		// 得到ioc容器
		Map<String, Object> ioc = BeanFactory.getIOC();
		if (ioc.isEmpty()) {
			return;
		}
		try {
			Set<String> keySet = ioc.keySet();
			for (String key : keySet) {
				Class<? extends Object> clazz = ioc.get(key).getClass();
				// 只处理controller 可以放开处理所有的注解情况
				if (!clazz.isAnnotationPresent(Controller.class))
					continue;
				// 类上的requestmapping
				String baseUrl = "";
				if (clazz.isAnnotationPresent(RequestMapping.class)) {
					RequestMapping annotation = clazz.getAnnotation(RequestMapping.class);
					baseUrl = annotation.value();
				}
				Method[] methods = clazz.getMethods();
				for (Method method : methods) {
					if (!method.isAnnotationPresent(RequestMapping.class))
						continue;
					RequestMapping annotation = method.getAnnotation(RequestMapping.class);
					String url = annotation.value();
					url = (baseUrl + "/" + url).replaceAll("/+", "/");
					handlerMapping.put(url, method);
					controllerMap.put(url, ioc.get(key));
				}
				System.out.println(handlerMapping);
				System.out.println(controllerMap);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try {
			doDispatch(req, resp);
		} catch (Exception e) {
			resp.getWriter().write("500!!!Server Exception");
		}
	}

	private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (handlerMapping.isEmpty())
			return;
		String uri = request.getRequestURI();
		String contentPath = request.getContextPath();
		uri = uri.replace(contentPath, "").replaceAll("/+", "/");
		if (!handlerMapping.containsKey(uri)) {
			response.getWriter().write("404 Not Found");
			return;
		}
		Method method = handlerMapping.get(uri);
		// 获取方法参数列表类型
		Class<?>[] parameterTypes = method.getParameterTypes();
		// 获取请求的参数
		Map<String, String[]> parameterMap = request.getParameterMap();
		// 保存参数值
		Object[] paramValues = new Object[parameterTypes.length];
		for (int i = 0; i < parameterTypes.length; i++) {
			// 根据参数名，进行处理
			String requestParam = parameterTypes[i].getSimpleName();
			if (requestParam.equals("HttpServletRequest")) {
				paramValues[i] = request;
				continue;
			}
			if (requestParam.equals("HttpServletResponse")) {
				paramValues[i] = response;
				continue;
			}
			if (requestParam.equals("String")) {
				for (Map.Entry<String, String[]> param : parameterMap.entrySet()) {
					String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "").replaceAll(",\\s", ",");
					paramValues[i] = value;
				}
			}
		}
		// 利用反射调用方法
		try {
			method.invoke(controllerMap.get(uri), paramValues);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
